package com.blue.rpc.core.message;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

/**
 * 消息转化Protostuff工具类
 * 
 * @author zhengj
 * @since 1.0 2017年3月13日
 */
public class MessageProtostuffConvertor
{
	private static Map<Class<?>, Schema<?>> cache = new ConcurrentHashMap<Class<?>, Schema<?>>();

	private MessageProtostuffConvertor()
	{
	}

	/**
	 * 把消息对象转化为字节数组byte[]
	 * 
	 * @param request 消息对象
	 * @return 字节数组byte[]
	 */
	@SuppressWarnings("unchecked")
	public static <T> byte[] toBytes(T obj)
	{
		Class<T> clazz = (Class<T>)obj.getClass();
		LinkedBuffer buffer = LinkedBuffer.allocate();
		try
		{
			Schema<T> schema = getSchema(clazz);
			return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
		}
		catch (Exception e)
		{
			throw new IllegalStateException(e.getMessage(), e);
		}
		finally
		{
			buffer.clear();
		}
	}

	/**
	 * 把字节数组byte[]转化为消息对象
	 * 
	 * @param bytes 字节数组
	 * @return 消息对象
	 */
	public static <T> T toObject(byte[] data, Class<T> clazz)
	{
		try
		{
			T message = clazz.newInstance();
			Schema<T> schema = getSchema(clazz);
			ProtostuffIOUtil.mergeFrom(data, message, schema);
			return message;
		}
		catch (Exception e)
		{
			throw new IllegalStateException(e.getMessage(), e);
		}
	}

	@SuppressWarnings("unchecked")
	private static <T> Schema<T> getSchema(Class<T> cls)
	{
		return (Schema<T>)cache.computeIfAbsent(cls, RuntimeSchema::createFrom);
	}

}
